package priv.lhy.user.services;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.SignatureException;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import priv.lhy.constans.WebConstant;
import priv.lhy.constants.Constans;
import priv.lhy.constants.ResponseCodeEnum;
import priv.lhy.constants.ServiceException;
import priv.lhy.dto.*;
import priv.lhy.user.IUserCoreService;
import priv.lhy.user.dal.entity.User;
import priv.lhy.user.dal.persistence.UserMapper;
import priv.lhy.user.exception.ExceptionUtil;
import priv.lhy.user.exception.ValidateException;
import priv.lhy.utils.JwtTokenUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * author : lihy
 * date : 2019/1/30 13:53
 * <p>
 * 用户操作service实现类
 */
@Service("userCoreService")
public class UserCoreServiceImpl implements IUserCoreService {

    Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    UserMapper userMapper;

    /**
     * 用户登录
     *
     * @param request
     * @return
     */
    @Override
    public UserLoginResponse login(UserLoginRequest request) {
        logger.info("login request: " + request);
        UserLoginResponse response = new UserLoginResponse();
        try {
            //验证请求
            beforeValidateLogin(request);
            User user = userMapper.getUserByUserName(request.getUsername());
            if (null == user || !user.getPassword().equals(request.getPassword())) {
                //登录失败
                response.setCode(ResponseCodeEnum.USERORPASSWORD_ERROR.getCode());
                response.setMsg(ResponseCodeEnum.USERORPASSWORD_ERROR.getMsg());
            } else {
                //登录成功
                Map<String, Object> map = new HashMap<>();
                map.put("uid", user.getId());
                map.put("exp", DateTime.now().plusSeconds(WebConstant.EXP_JWT).toDate().getTime() / 1000);
                //设置token
                response.setToken(JwtTokenUtils.generatorToken(map));
                //设置其他信息
                response.setUid(user.getId());
                response.setAvatar(user.getAvatar());
                response.setCode(ResponseCodeEnum.SUCCESS.getCode());
                response.setMsg(ResponseCodeEnum.SUCCESS.getMsg());
            }
        } catch (Exception e) {
            logger.error("login occur exception: " + e);
            //抛转异常，根据异常类型获取返回信息
            ServiceException se = (ServiceException) ExceptionUtil.handlerException4biz(e);
            response.setCode(se.getErrorCode());
            response.setMsg(se.getErrorMessage());
        } finally {
            logger.info("[" + request + "] login response: " + response);
        }
        return response;
    }

    /**
     * token验证
     *
     * @param request
     * @return
     */
    @Override
    public CheckAuthResponse validToken(CheckAuthRequest request) {
        CheckAuthResponse response = new CheckAuthResponse();
        try {
            //验证请求
            beforeValidateAuth(request);
            //获取token数据
            Claims claims = JwtTokenUtils.phaseToken(request.getToken());
            //验证成功
            response.setUid(claims.get("uid").toString());
            response.setCode(ResponseCodeEnum.SUCCESS.getCode());
            response.setMsg(ResponseCodeEnum.SUCCESS.getMsg());
            //更新过期时间
            Map<String, Object> map = new HashMap<>();
            map.put("uid", claims.get("uid").toString());
            map.put("exp", DateTime.now().plusSeconds(WebConstant.EXP_JWT).toDate().getTime() / 1000);
            //设置token
            response.setToken(JwtTokenUtils.generatorToken(map));
        } catch (ExpiredJwtException e) {
            //token超时
            logger.error("Expire: " + e.getMessage());
            response.setCode(ResponseCodeEnum.TOKEN_EXPIRE.getCode());
            response.setMsg(ResponseCodeEnum.TOKEN_EXPIRE.getMsg());
        } catch (SignatureException e1) {
            //签名错误
            logger.error("SignatureException: " + e1.getMessage());
            response.setCode(ResponseCodeEnum.SIGNATURE_ERROR.getCode());
            response.setMsg(ResponseCodeEnum.SIGNATURE_ERROR.getMsg());
        } catch (Exception e2) {
            //其他异常
            logger.error("login occur exception: " + e2.getMessage());
            ServiceException se = (ServiceException) ExceptionUtil.handlerException4biz(e2);
            response.setCode(se.getErrorCode());
            response.setMsg(se.getErrorMessage());
        } finally {
            logger.info("[" + request + "] response: " + response);
        }
        return response;
    }

    /***
     * 用户注册
     *
     * @param request
     * @return
     */
    @Override
    public UserRegisterResponse register(UserRegisterRequest request) {
        logger.info("begin UserCoreService.regiter, request:[" + request + "]");
        UserRegisterResponse response = new UserRegisterResponse();
        try {
            beforeRegisterValidate(request);
            User user = new User();
            user.setUsername(request.getUsername());
            user.setPassword(request.getPassword());
            user.setMobile(request.getMobile());
            user.setStatus(Constans.NORMAL_UESR_STATUS);
            user.setCreateTime(new Date());

            int effectRow = userMapper.insertSelective(user);
            if (effectRow > 0) {
                response.setCode(ResponseCodeEnum.SUCCESS.getCode());
                response.setMsg(ResponseCodeEnum.SUCCESS.getMsg());

                Map<String, Object> map = new HashMap<>();
                map.put("uid", user.getId());
                map.put("exp", DateTime.now().plusSeconds(WebConstant.EXP_JWT).toDate().getTime() / 1000);
                //设置token
                response.setToken(JwtTokenUtils.generatorToken(map));

            } else {
                response.setCode(ResponseCodeEnum.SYSTEM_BUSY.getCode());
                response.setMsg(ResponseCodeEnum.SYSTEM_BUSY.getMsg());
            }
        } catch (Exception e) {
            ServiceException se = (ServiceException) ExceptionUtil.handlerException4biz(e);
            response.setCode(se.getErrorCode());
            response.setMsg(se.getErrorMessage());
        } finally {
            logger.info("[" + request + "]register response: " + response);
        }

        return response;
    }

    /**
     * 注册前验证
     * @param request
     */
    private void beforeRegisterValidate(UserRegisterRequest request) {
        if (null == request) {
            throw new ValidateException("请求对象为空");
        }
        if (StringUtils.isEmpty(request.getUsername())) {
            throw new ValidateException("用户名为空");
        }
        if (StringUtils.isEmpty(request.getPassword())) {
            throw new ValidateException("密码为空");
        }
        if (StringUtils.isEmpty(request.getMobile())) {
            throw new ValidateException("手机号为空");
        }
    }

    /**
     * 权限前验证
     * @param request
     */
    private void beforeValidateAuth(CheckAuthRequest request) {
        if (null == request) {
            throw new ValidateException("请求对象为空");
        }
        if (StringUtils.isEmpty(request.getToken())) {
            throw new ValidateException("token信息为空");
        }
    }

    /**
     * 登录前验证
     * @param request
     */
    private void beforeValidateLogin(UserLoginRequest request) {
        if (null == request) {
            throw new ValidateException("请求对象为空");
        }
        if (StringUtils.isEmpty(request.getUsername())) {
            throw new ValidateException("用户名为空");
        }
        if (StringUtils.isEmpty(request.getPassword())) {
            throw new ValidateException("密码为空");
        }
    }
}
